package com.lp.security.schedule;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.lp.biz.member.mapper.MemberMapper;
import com.lp.biz.member.model.entity.Member;
import com.lp.biz.members.mapper.BizMembersRelMapper;
import com.lp.biz.members.model.entity.BizMembersRel;
import com.lp.biz.message.model.entity.BizMessageSystem;
import com.lp.biz.message.service.BizMessageSystemService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.*;

import static com.lp.common.constant.CommonConstant.*;

/**
 * @program: backend
 * @description: 定时将过期会员修改
 * @author: Ke.Song
 * @since: 2024-04-14 22:26:35
 */
@Slf4j
@Component
public class MembersExpire {

    @Autowired
    private BizMembersRelMapper membersRelMapper;

    @Autowired
    private MemberMapper memberMapper;

    @Autowired
    private BizMessageSystemService messageSystemService;

    @Scheduled(cron = "0 0 1 * * ?")
    @Transactional(rollbackFor = RuntimeException.class)
    public void checkMembersExpire() {
        // 记录操作开始
        log.info("开始检查会员过期时间");

        // 使用HashSet存储需要更新为已过期状态的会员ID
        Set<Integer> memberIds = new HashSet<>(6);
        for (Member member : memberMapper.selectList(new QueryWrapper<Member>().lambda()
                .eq(Member::getIsMembers, SURE)
                .eq(Member::getMembersExpiryAt, LocalDate.now().minusDays(1)))) {
            memberIds.add(member.getId());
        }

        // 如果有会员已过期，则更新会员关系表中的过期状态，并为这些会员发送过期通知
        if (!memberIds.isEmpty()) {
            membersRelMapper.update(null, new UpdateWrapper<BizMembersRel>()
                    .lambda()
                    .in(BizMembersRel::getMemberId, memberIds)
                    .eq(BizMembersRel::getIsExpired, SURE)
                    .set(BizMembersRel::getIsExpired, NEGATE));
            memberMapper.update(null, new UpdateWrapper<Member>()
                    .lambda().in(Member::getId, memberIds)
                    .set(Member::getIsMembers, NEGATE)
                    .set(Member::getMembersExpiryAt, null));

            // 为每个已过期的会员发送通知
            for (Integer memberId : memberIds) {
                BizMessageSystem messageSystem = messageSystemService.membersExpire();
                messageSystem.setMemberId(memberId);
                messageSystemService.save(messageSystem);
            }
        }

        // 记录操作结束
        log.info("会员时间校验结束");
    }

    /**
     * 定时任务，每天零点检查即将到期的会员。
     * 使用CRON表达式"0 0 0 * * ?"指定每天凌晨0点执行该任务。
     * 事务管理配置，指定回滚策略为针对RuntimeException类及其子类。
     */
    @Scheduled(cron = "0 30 1 * * ?")
    @Transactional(rollbackFor = RuntimeException.class)
    public void checkMembersToExpire() {
        // 记录任务开始时间
        log.info("开始检查还有7天到期的会员");
        for (Member member : memberMapper.selectList(new QueryWrapper<Member>().lambda()
                .eq(Member::getIsMembers, SURE)
                .eq(Member::getMembersExpiryAt, LocalDate.now().plusDays(6)))) {
            BizMessageSystem messageSystem = messageSystemService.membersToExpire();
            messageSystem.setMemberId(member.getId());
            // 保存消息到系统中
            messageSystemService.save(messageSystem);
        }
        // 记录任务完成时间
        log.info("7天到期的会员校验结束");
    }
}
